package auth

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"code.gitea.io/gitea/services/context"

	wechat_model "code.gitea.io/gitea/models/wechat"
	"code.gitea.io/gitea/modules/log"
	"code.gitea.io/gitea/modules/setting"
	wechat_service "code.gitea.io/gitea/services/wechat"
)

// Define a Wechat Error type message
type WechatError struct {
	message string
}

// Implement the Error() method for the `WechatError` type
func (e *WechatError) Error() string {
	return e.message
}

type ResponseData struct {
	Code int                             `json:"code"`
	Msg  string                          `json:"msg"`
	Data wechat_service.WechatTempQRData `json:"data"`
}

/**
 * GetWechatQRTicket 生成微信官方账户临时二维码
 *
 * @return string 生成的微信二维码的 ticket
 * @return string 生成的微信二维码图片URL
 * @return error 如果生成二维码过程中出现错误，则返回相应的错误信息
 */
func GetWechatQRTicket(ctx *context.Context) (wechatQrTicket string, QRImageURL string, errorGenerateQr error) {

	sceneStr := setting.Domain
	qrExpireSeconds := setting.Wechat.TempQrExpireSeconds

	// 构建请求的 URL
	url := fmt.Sprintf("https://%s/api/wechat/login/qr/generate?qrExpireSeconds=%d&sceneStr=%s", setting.Wechat.DefaultDomainName, qrExpireSeconds, sceneStr)

	// 发送 GET 请求
	resp, err := http.Get(url)
	if err != nil {
		return "", "", fmt.Errorf("failed to send GET request: %v", err)
	}
	defer resp.Body.Close()

	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", "", fmt.Errorf("failed to read response body: %v", err)
	}
	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return "", "", fmt.Errorf("received non-200 response status: %s", resp.Status)
	}

	// 解析 JSON 响应
	var data ResponseData
	if err := json.Unmarshal(bodyBytes, &data); err != nil {
		return "", "", fmt.Errorf("failed to unmarshal JSON response: %v", err)
	}
	quit := make(chan bool) // 用来通知goroutine停止
	// 启动一个新的goroutine来进行轮询
	go func() {
		// 创建一个超时定时器通道
		timeout := time.After(time.Duration(qrExpireSeconds) * time.Second)
		ticker := time.NewTicker(1 * time.Second)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				checkWechatQrTicketStatus(ctx, wechatQrTicket, quit)

			case <-quit:
				log.Info("Stopping polling...")
				return

			case <-timeout:
				log.Info("Polling timed out after", qrExpireSeconds, "seconds.")
				quit <- true // 发送停止信号给轮询goroutine
			}
		}
	}()
	return data.Data.Ticket, data.Data.QrImageSrcUrl, nil
}

// Response represents the top-level JSON structure
type Response struct {
	Code int                               `json:"code"`
	Msg  string                            `json:"msg"`
	Data wechat_service.WechatTempQRStatus `json:"data"`
}

// 假设这是用于检查二维码状态的函数
func checkWechatQrTicketStatus(ctx *context.Context, qrTicket string, quit chan bool) {

	url := fmt.Sprintf("https://%s/api/wechat/login/qr/check-status?ticket=%s&_=%d",
		setting.Wechat.DefaultDomainName, qrTicket, time.Now().UnixMilli())

	resp, err := http.Get(url)
	if err != nil {
		log.Error("There was a problem with the fetch operation:", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		log.Error("Network response was not ok")
		return
	}

	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Error("Error reading response body:", err)
		return
	}
	// 解析 JSON 响应
	var data Response
	if err := json.Unmarshal(bodyBytes, &data); err != nil {
		log.Error("failed to unmarshal JSON response: %v", err)
		return
	}
	if data.Code == 0 && data.Data.IsScanned {
		log.Info("Caching WeChat QR Scanned Info: %s\n", bodyBytes)
		// {"code":0,"msg":"操作成功","data":{
		// "is_scanned":true,
		// "scene_str":"2d521f80047c42aba27ee9beade35985@p2Z6hfheDxg=",
		// "openid":"oQowJ6cD9WSuoxYaCc7mryfn-lVo",
		// "is_binded":true}}
		// 准备扫码状态VO对象
		qrStatus := wechat_service.WechatTempQRStatus{
			SceneStr:  data.Data.SceneStr,
			IsScanned: data.Data.IsScanned,
			OpenId:    data.Data.OpenId,
		}
		// 从微信服务器消息推送中解析扫码人的 OpenId
		user, err := wechat_model.QueryUserByOpenid(ctx, qrStatus.OpenId)
		if user == nil {
			// 未找到 OpenId 对应的 DevStar 用户信息，提示前端导向注册页
			qrStatus.IsBinded = false
			qrStatusString, err := qrStatus.Marshal2JSONString()
			if err == nil {
				// 将扫码人的微信公众号 OpenId 标记为等待注册，等待时间用户注册完成，默认24小时
				//    key:  qrScanResponseDigest.Ticket
				//  value:  JSON 字符串
				//    TTL:  setting.Wechat.TempQrExpireSeconds
				wechat_service.SetWechatQrTicketWithTTL(
					qrTicket,
					qrStatusString,
					setting.Wechat.RegisterationExpireSeconds)
			}
			quit <- true
			return
		}

		qrStatus.IsBinded = true
		qrVOJsonString, err := qrStatus.Marshal2JSONString()
		if err == nil {
			wechat_service.SetWechatQrTicketWithTTL(
				qrTicket,
				qrVOJsonString,
				setting.Wechat.TempQrExpireSeconds)
		}
		quit <- true
		return
	}
}
